面试官常问的Spring依赖注入和Bean的装配问题,今天给大家讲清楚!

您所在的位置:网站首页 bean beans区别 面试官常问的Spring依赖注入和Bean的装配问题,今天给大家讲清楚!

面试官常问的Spring依赖注入和Bean的装配问题,今天给大家讲清楚!

2024-07-10 00:27| 来源: 网络整理| 查看: 265

写在前面

小伙伴儿们,Spring 的依赖注入以及 Bean 的装配是面试常问的知识点,今天我们来学习一下Spring中的依赖注入方式,以及如何将自己开发的Bean装配到Spring IoC容器中。

思维导图

思维导图

1、依赖注入方式1.1、setter注入;

setter注入是Spring中最主流的注入方式,它利用Java Bean规范所定义的setter方法来完成注入,灵活且可读性高。

比方说我刚开始输出一个对象的话,看代码:

先建立一个实体类People:代码语言:javascript复制package com.java.entity; public class People { private int id; private String name; private int age; public People() { //调用默认的构造方法 } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } 然后是配置文件ApplicationContext.xml:代码语言:javascript复制 再来个测试类:代码语言:javascript复制package com.java.test; import com.java.entity.People; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test2 { public static void main(String[] args) { //加载beans.xml文件,调用Spring接口 ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml"); //通过id获取bean,返回一个对象 People people=(People)ac.getBean("people"); //调用方法 System.out.println(people); } }

我们看运行结果:

那么,setter注入又是怎么回事呢?

setter注入就是可以在beans配置文件中主动加入属性,以此来改变输出对象的特点;

我们在People类里面添加一下构造函数,并重写一下toString方法:代码语言:javascript复制public People() { //调用默认的构造方法 } @Override public String toString() { return "People{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + '}'; } 在配置文件中加入属性:代码语言:javascript复制//属性注入 测试函数:代码语言:javascript复制//属性注入 People people2=(People)ac.getBean("people2"); System.out.println(people2);

我们看运行效果:

1.2、构造器注入;

构造器注入依赖于构造方法实现,而构造方法可以是有参数或者无参数。在大部分的情况下,我们都是通过类的构造方法来创建对象,Spring也可以采用反射的方式,通过使用构造方法来完成注入,这就是构造器注入的原理。

我们来看看实例:

先要把实体类的属性构造方法加上:代码语言:javascript复制public People(int id, String name, int age) { this.id = id; this.name = name; this.age = age; } 然后是配置文件:代码语言:javascript复制 测试函数:代码语言:javascript复制 //类型注入 People people3=(People)ac.getBean("people3"); System.out.println(people3); //索引注入 People people4=(People)ac.getBean("people4"); System.out.println(people4); //联合使用 People people5=(People)ac.getBean("people5"); System.out.println(people5);

运行结果:

2、装配Bean

前面已经介绍了Spring IoC的理念和设计,现在我们来学习一下如何将自己开发的Bean装配到Spring IoC容器中;

大部分场景下,我们都会使用 ApplicationContext 的具体实现类,因为对应的 Spring IoC 容器功能相对强大。

而在 Spring 中提供了 3 种方法进行配置:

在 XML 中显式配置在 Java 的接口和类中实现配置隐式 Bean 的发现机制和自动装配原则

在现实的工作中,这 3 种方式都会被用到,并且在学习和工作之中常常混合使用,所以这里给出一些关于这 3 种优先级的建议:

(1)最优先:通过隐式 Bean 的发现机制和自动装配的原则。

基于约定优于配置的原则,这种方式应该是最优先的好处:减少程序开发者的决定权,简单又不失灵活。

(2)其次:Java 接口和类中配置实现配置

在没有办法使用自动装配原则的情况下应该优先考虑此类方法好处:避免 XML 配置的泛滥,也更为容易。典型场景:一个父类有多个子类,比如学生类有两个子类,一个男学生类和女学生类,通过 IoC 容器初始化一个学生类,容器将无法知道使用哪个子类去初始化,这个时候可以使用 Java 的注解配置去指定。

(3)最后:XML 方式配置

在上述方法都无法使用的情况下,那么也只能选择 XML 配置的方式。好处:简单易懂典型场景:当使用第三方类的时候,有些类并不是我们开发的,我们无法修改里面的代码,这个时候就通过 XML 的方式配置使用了。2.1,通过XML方式配置装配Bean;

使用 XML 装配 Bean 需要定义对应的 XML,这里需要引入对应的 XML 模式(XSD)文件,这些文件会定义配置 Spring Bean 的一些元素,比方说当我们在 IDEA 中创建 XML 文件时,就会有对应的配置文件(Spring Config)提示,也就是上面所说的XSD文件:

2.1.1,简单的配置如下代码语言:javascript复制

我们在这里面需要引入 beans 的定义,引入xsd 文件,它是一个根元素,这样它所定义的元素将可以定义对应的 Spring Bean;

id:对象的唯一标识;class:bean的完全限定名称,从包名称到类名称;property:给属性赋值,name的名称取决于set()方法后面的参数,ref引用具体的值;

这里的详细在我上一篇文章中有详解,这里就不再赘述了。

2.1.2,装配集合

有些时候需要做一些复杂的装配工作,比如 Set、Map、List、Array 和 Properties 等,为此我们新建一个 ComplexAssembly 类:

代码语言:javascript复制package com.java.ssm; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; public class ComplexAssembly { private Long id; private List list; private Map map; private Properties properties; private Set set; private String[] array; }

这个 Bean 没有任何的实际意义,只是为了介绍如何装配这些常用的集合类:

代码语言:javascript复制 value-list-1 value-list-2 value-list-3 value-prop-1 value-prop-2 value-prop-3 value-set-1 value-set-2 value-set-3 value-array-1 value-array-2 value-array-3

总结:

List 属性为对应的 元素进行装配,然后通过多个 元素设值。Map 属性为对应的 元素进行装配,然后通过多个 元素设值,只是 entry 包含一个键值对(key-value)的设置Properties 属性为对应的 元素进行装配,通过多个 元素设值,只是 properties 元素有一个必填属性 key ,然后可以设置值Set 属性为对应的 元素进行装配,然后通过多个 元素设值对于数组而言,可以使用 设置值,然后通过多个 元素设值。

集合注入总结:

List 属性使用 元素定义注入,使用多个 元素的 Bean 属性去引用之前定义好的 BeanMap 属性使用 元素定义注入,使用多个 元素的 key-ref 属性去引用之前定义好的 Bean 作为键,而用 value-ref 属性引用之前定义好的 Bean 作为值Set 属性使用 元素定义注入,使用多个 元素的 bean 去引用之前定义好的 Bean2.2,通过注解装配Bean

通过上面的学习,我们已经了解了如何使用 XML 的方式去装配 Bean,但是更多的时候已经不再推荐使用 XML 的方式去装配 Bean,更多的时候会考虑使用注解(annotation) 的方式去装配 Bean。

优点:

减少XML配置,注解功能更为强大,既能实现 XML 的功能,也提供了自动装配的功能,采用了自动装配后,程序员所需要做的决断就少了,更加有利于对程序的开发,这就是“约定优于配置”的开发原则。

在 Spring 中,它提供了两种方式来让 Spring IoC 容器发现 Bean;

组件扫描:通过定义资源的方式,让 Spring IoC 容器扫描对应的包,从而把 Bean 装配进来。自动装配:通过注解定义,使得一些依赖关系可以通过注解完成。2.2.1,使用@Component装配Bean

举个栗子,我们创建一个People类:

代码语言:javascript复制package com.java.test; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component(value="people") public class People { @Value("1") private int id; @Value("jack") private String name; }

注解的相关解释:

@Component注解:表示 Spring IoC 会把这个类扫描成一个 Bean 实例,而其中的 value 属性代表这个类在 Spring 中的 id,这就相当于在 XML 中定义的 Bean 的 id:,也可以简写成 @Component("people"),甚至直接写成 @Component ,对于不写的,Spring IoC 容器就默认以类名来命名作为 id,只不过首字母小写,配置到容器中。@Value注解:表示值的注入,跟在 XML 中写 value 属性是一样的。

这样我们就创建好了一个Bean,相当于XML中类似的配置:

代码语言:javascript复制

现在有了这个类,但是还不能进行测试,因为Spring IoC并不知道需要去哪里扫描对象,这个时候我们可以使用一个 PeopleConfig 类去告诉 Spring IoC :

代码语言:javascript复制package com.java.test; import org.springframework.context.annotation.ComponentScan; @ComponentScan public class PeopleConfig { }

这个类十分简单,没有任何逻辑,但是需要说明两点:

该类和 People类位于同一包名下@ComponentScan注解:代表进行扫描,默认是扫描当前包的路径,扫描所有带有 @Component 注解的类。

这样一来,我们就可以通过 Spring 定义好的 Spring IoC 容器的实现类——AnnotationConfigApplicationContext 去生成 IoC 容器了:

代码语言:javascript复制ApplicationContext context = new AnnotationConfigApplicationContext(PeopleConfig.class); People people = (People) context.getBean("people", People.class); people.printInformation();

这里可以看到使用了 AnnotationConfigApplicationContext 类去初始化 Spring IoC 容器,它的配置项是 PeopleConfig 类,这样 Spring IoC 就会根据注解的配置去解析对应的资源,来生成 IoC 容器了。

2.2.2,自动装配@Autowired

所谓自动装配技术是一种由 Spring 自己发现对应的 Bean,自动完成装配工作的方式,它会应用到一个十分常用的注解 @Autowired 上,这个时候 Spring 会根据类型去寻找定义的 Bean 然后将其注入,举个实例看看:

1,先创建一个PeopleService接口:

代码语言:javascript复制package com.java.service; public interface PeopleService { public void printPeopleInfo(); }

2,为上面接口创建一个PeopleServiceImp实现类:

代码语言:javascript复制package com.java.service; import com.java.test.People; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component("peopleService") public class PeopleServiceImp implements PeopleService{ @Autowired private People people=null; public void printPeopleInfo(){ System.out.println("人的id为:"+people.getId()); System.out.println("人的name为:"+people.getName()); } }

该实现类实现了接口的 printPeopleInfo() 方法,打印出成员对象 people的相关信息,这里的 @Autowired 注解,表示在 Spring IoC 定位所有的 Bean 后,这个字段需要按类型注入,这样 IoC 容器就会寻找资源,然后将其注入。

3,测试类:

修改PeopleConfig类,告诉Spring IoC的扫描路径:

代码语言:javascript复制package com.java.test; import org.springframework.context.annotation.ComponentScan; @ComponentScan(basePackages = {"com.java.test","com.java.service"}) public class PeopleConfig { }

然后是测试函数:

代码语言:javascript复制package com.java.service; import com.java.test.People; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component("peopleService") public class PeopleServiceImp implements PeopleService{ @Autowired private People people=null; public void printPeopleInfo(){ System.out.println("人的id为:"+people.getId()); System.out.println("人的name为:"+people.getName()); } }

运行结果:

@Autowired 注解表示在 Spring IoC 定位所有的 Bean 后,再根据类型寻找资源,然后将其注入。过程: 定义 Bean —— 初始化 Bean —— 根据属性需要从 Spring IoC 容器中搜寻满足要求的 Bean —— 满足要求则注入问题: IoC 容器可能会寻找失败,此时会抛出异常(默认情况下,Spring IoC 容器会认为一定要找到对应的 Bean 来注入到这个字段,但有些时候并不是一定需要,比如日志)解决: 通过配置项 required 来改变,比如 @Autowired(required = false)

@Autowired 注解不仅仅能配置在属性之上,还允许方法配置,常见的 Bean 的 setter 方法也可以使用它来完成注入,总之一切需要 Spring IoC 去寻找 Bean 资源的地方都可以用到,例如:

代码语言:javascript复制public class Spring { ...... @Autowired public void setSource(Source source) { this.source = source; } }

在大部分的配置中都推荐使用@Autowired自动注入来完成,这是 Spring IoC 帮助我们自动装配完成的,这样使得配置大幅度减少,满足约定优于配置的原则,增强程序的健壮性。

小结

本文我们学会了装配Bean的常用方式,常用的是通过注解装配Bean,也就是基于约定优于配置的原则。后面我们继续来探讨一下Bean的作用域与生命周期等流程。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3